use rustcloud_core::{Request, ServiceInstance, ServiceRegistry, LoadBalancerStrategy, TransportConfig};
use rustcloud_registry::InMemoryRegistry;
use rustcloud_loadbalancer::LoadBalancerManager;
use rustcloud_transport::HttpTransport;
use rustcloud_proxy::ServiceProxy;
use std::sync::Arc;
use wiremock::{MockServer, Mock, ResponseTemplate};
use wiremock::matchers::{method, path};
use rustcloud_circuit_breaker::{DefaultCircuitBreaker, CircuitBreakerConfig};

#[tokio::test]
async fn test_full_end_to_end_flow() {
    // 1. 模拟一个远程服务
    let server = MockServer::start().await;
    let mock_response_body = "Hello from Mock Server!";
    Mock::given(method("POST"))
        .and(path("/api/hello-service/say_hello"))
        .respond_with(ResponseTemplate::new(200).set_body_string(mock_response_body))
        .mount(&server)
        .await;

    // 2. 使用内存注册中心注册这个 mock 服务
    let registry = Arc::new(InMemoryRegistry::new());
    let server_uri = server.uri();
    let parts: Vec<&str> = server_uri.split(':').collect();
    let host = parts[1].trim_start_matches("//");
    let port = parts[2].parse::<u16>().unwrap();

    let instance = ServiceInstance::new("hello-service", host, port, "http");
    registry.register(instance).await.unwrap();

    // 3. 构建完整的调用链路
    let load_balancer = Arc::new(LoadBalancerManager::new(LoadBalancerStrategy::RoundRobin));
    let transport = Arc::new(HttpTransport::new());
    let circuit_breaker = Arc::new(DefaultCircuitBreaker::new(CircuitBreakerConfig::default()));
    let proxy = ServiceProxy::new(registry, load_balancer, transport, circuit_breaker);

    // 4. 发起真实调用
    let mut request = Request::new("hello-service", "POST", "/api/hello-service/say_hello");
    request.set_body(b"some body".to_vec()); // Add a body to match POST

    let transport_config = TransportConfig::default();
    let response = proxy.call(request, &transport_config).await.unwrap();

    // 5. 验证结果
    assert_eq!(response.status, 200);
    let body = String::from_utf8(response.body.unwrap()).unwrap();
    assert_eq!(body, mock_response_body);
}
